NOTE: ED!SON is not a PC cracker but he's tutorial is great for newbies. ED!SON is a United Cracking Force cracker. Windows Cracking Tutorial v1.o Page 1 of 7 =========================================== ED!SON's Windows 95 Cracking Tutorial v1.oo =========================================== CONTENTS ======== 1. Introduction to Windows cracking 2. Quick introduction to SoftICE/Win 2.oo 3. Finding registration codes 3.1 Task Lock 3.00 - A simple registration number only protection 3.2 Command Line 95 - Easy name/code registration 4. Making a keymaker for Command Line 95 5. How PUSH and CALL and things really work when the program call a function 6. About Visual Basic programs APPENDIX ======== A. Making SoftICE load symbols B. Syntax for the functions C. Where to obtain the softwares D. Contacting me 1. INTRUDUCTION TO WINDOWS CRACKING =================================== Cracking a Windows program is most often more simple than a program running in Dos. In Windows, it's hard to hide anything from anyone who really looks for information, as long as Windows own functions are used. The first (and often only) tool you need is SoftICE/Win 2.oo, a powerful debugger from NuMega. Some people find it hard to use, but I will tell you how to do efficient debugging with it, and I hope you'll understand me :-) I have made an Appendix (A) with some SoftICE/Win 2.oo info you should read. I never had any problems installing SoftICE, so if you have, I'll have to refer to the manual. URLs to all software you need are in Appendix C. - ED!SON, edison@ccnux.utm.my 2. QUICK INTRODUCTION TO SOFTICE/WIN 2.OO ========================================= This should be a fairly bad view of the SoftICE screen layout: |--------------------| | Registers | Use 'R' to edit |--------------------| | Data Window | Use 'D' to view an address, 'E' to edit |--------------------| | Code Window | Use 'U' to view an address, 'A' to insert asm code |--------------------| | Command Window | Type commands and read output here |--------------------| Other important keys are (in the default key layout): 'H'/F1 - On-line help F5/Ctr+D - Run F8 - Step into functions F10 - Step over functions F11 - Step out of function 3. FINDING REGISTRATION CODES ============================= This is probably the easiest way to practice, to get a shareware program and try to register it. 3.1 Task Lock 3.00 - A simple registration number only protection ================================================================= This is a simple protection, only a code, that doesn't change. 3.1.1 Examining the program =========================== Is it 16 or 32 bit? Where do I enter registration information? Does the help give me any clue on how the registration works? Go and have a find out before you continue! ....You should be checking now!...Are you checking?...Have you checked?... OK, now you know it's a 32-bit Windows 95 application, and that you can register the program by entering a single Registration Number in a dialog box that appears when choosing the menu "Register|Register...". You also know, by reading in help, that there are two types of registration: Individual and Site License. So most probable there will be TWO checks for valid codes. 3.1.2 Trap the code routine =========================== The codes are usually entered in normal Windows Edit boxes. To check the code, the program must read the contents of the Edit box with one of these functions: 16-bit 32-bit ------ ------ GetWindowText GetWindowTextA, GetWindowTextW GetDlgItemText GetDlgItemTextA, GetDlgItemTextW The last letter of the 32-bit functions tell if the function uses one-byte or double-byte strings. Double-byte code is RARE. Maybe you got my idea... "If I only could break on GetWindowText" And - you can! But first you must be sure that these symbols are loaded by SoftICE. (See Appendix A) To set up a "trap" (really called breakpoint) in SoftICE, you first enter the debugger with Ctrl+D, then use the command BPX followed by the name of the function or a memory address. And Task Lock is 32-bit so let's put a breakpoint on GetWindowTextA. If that doesn't work, we can try the others. Type like this in SoftICE: :bpx getwindowtexta If you get an error message like "No LDT", make sure you don't run any other applications in the background. I've noticed that Norton Commander/Dos disturbs this function. You can check if you got any breakpoint by listing breakpoints: :bl This would give something like: 00) BPX USER32!GetWindowTextA C=01 To get out of SoftICE, you press Ctrl+D again Well, anyway, you have set your breakpoint that will trap any call to GetWindowTextA. Now let's try to enter some value in the registration number field and press OK... You press OK... and you just get a stupid message box telling you your code was wrong. So it wasn't GetWindowTextA... Let's try GetDlgItemTextA. First we erase the old breakpoint: :bc 0 (0 means number of breakpoint in the breakpoint list) And now set the new one: :bpx getdlgitemtexta Let's try again... 3.1.3 In the debugger ===================== Wow! It worked! You're now inside SoftICE, at the place where the function GetDlgItemTextA starts. To jump to wherever it was called from, press the key F11. You are now inside SGLSET.EXE, if you're not sure, look on the line between the code and the command window, it should look something like this: ----------SGLSET!.text+1B13---------- You can also disable the breakpoint now by doing this: :bd 0 To enable it later if you want to run again do like this then: :be 0 The first line in the code window looks like this: CALL [USER32!GetDlgItemTextA] To see the lines above, press Ctrl+Up arrow a few times, until you see the lines below. If you don't know anything about Assembler, I have added comments to the lines. RET ; End of function PUSH EBP ; Beginning of function MOV EBP, ESP ; ... SUB ESP, 0000009C ; ... PUSH ESI ; ... > LEA EAX, [EBP-34] ; EAX = EBP-34 PUSH EDI ; ... MOVE ESI, ECX ; ... PUSH 32 ; Save: Maximum size of string > PUSH EAX ; Save: Address of text buffer PUSH 000003F4 ; Save: Identifier of control PUSH DWORD PTR [ESI+1C] ; Save: Handle of dialog box CALL [USER32!GetDlgItemTextA] ; Get the text The PUSH commands means save the values for later use. I have marked the important lines with a '>' char. By looking at this we know that the address to the text buffer was stored in EAX, and that EAX was EBP-34. So now we look at EBP-34 like this: :d ebp-3 You should now be able to read what you entered if you look in the data window. Now we have to find a place where your code is matched with a working one. So we step through the program one instruction at a time with F10 until we find something about EBP-34... You don't step for very long until this code pops up: > LEA EAX, [EBP+FFFFFF64] ; EAX = EBP-9C LEA ECX, [EBP-34] ; ECX = EBP-34 PUSH EAX ; Save: EAX PUSH ECX ; Save: ECX > CALL 00403DD0 ; Call a function ADD ESP, 08 ; Erase saved information TEST EAX, EAX ; Check function return JNZ 00402BC0 ; Jump if not zero To me, this looks directly like a string compare function. They work like this: * Input two strings, return zero if equal, otherwise non-zero And why should the program compare a string with the one you entered? To see if it was valid! (As you probably already have figured out) Well, what is hiding behind the address [EBP+FFFFFF64] then? SoftICE doesn't handle negative numbers very well, so to find out the real value of this you do this calculation: 100000000 - FFFFFF64 = 9C You can do the calculation in SoftICE like this: :? 0-FFFFFF64 The number 100000000 is too big for SoftICE, but on the other hand it gives the same result. And now... time to look what hides behind EBP-9C... Do like this: :d ebp-9c The data window will now show a long row of numbers - the code! But remember what I said earlier... two types of registration gives two codes... so after you've written down the code you got, we continue stepping width F10... We come to this piece of code: > LEA EAX, [EBP-68] ; EAX = EBP-68 LEA ECX, [EBP-34] ; ECX = EBP-34 PUSH EAX ; Save: EAX PUSH ECX ; Save: ECX > CALL 00403DD0 ; Call the function again ADD ESP, 08 ; Erase saved information TEST EAX, EAX ; Check function return JNZ 00402BFF ; Jump if not zero And what can you find at the address EBP-68? Well... another registration code! :d ebp-68 That's it... I hope everything worked! 3.2 Command Line 95 - Easy name/code registration, and we make a keymaker ========================================================================== This is a nice sample program, with a very easy code calculation. 3.1.1 Examining the program =========================== You examine the program and you see it's a 32-bit application, demanding Name and Code in the registration dialog. So let's start! 3.1.2 Trap the code routine =========================== We do as with TaskLock - we set breakpoints. We can set breakpoints on both of the two most probable functions: GetWindowTextA and GetDlgItemTextA. Press Ctrl+D to make SoftICE show up, and then: :bpx getwindowtexta :bpx getdlgitemtexta Now go to the registration dialog, and enter a name and some number (an integer is the most usual code). I wrote like this, and pressed OK... Name: ED!SON '96 Code: 12345 The program stopped at GetDlgItemTextA. Just like with TaskLock, we press F11 to return to the calling function. We scroll upwards with Ctrl+Up and the call looks like this: MOV ESI, [ESP+0C] PUSH 1E ; Maximum length PUSH 0040A680 ; Address to buffer PUSH 000003ED ; Control handle PUSH ESI ; Dialog handle CALL [User32!GetDlgItemTextA] The number 40A680 looks interesting to us, so we check that address: :d 40a680 And what shows up in the data window, if not the name we entered. Well, we look below the above piece of code, and it says: PUSH 00 ; (not interesting) PUSH 00 ; (not interesting) PUSH 000003F6 ; Control handle MOV EDI, 0040A680 ; Save address to buffer PUSH ESI ; Dialog handle CALL [User32!GetDlgItemInt] GetDlgItemInt is similar to GetDlgItemText, but it returns an integer from the text box. It is returned in EAX, so we step past these instructions, and look in the registers window... For me it says: EAX=00003039 And what is hex 3039? Type: :? 3039 And you get this: 00003039 0000012345 "09" ^ hex ^ dec ^ ascii And, as you can see (and already had guessed), it shows the code you wrote. Ok, what now? Let's look at the code that follows, first the return code is saved: MOV [0040A548], EAX ; Save return code MOV EDX, EAX ; Put return code in DX too 3.1.3 Calculating the code ========================== Then the code is calculated! MOV ECX, FFFFFFFF ; These rows calc string length SUB EAX, EAX ; . REPNZ SCASB ; . NOT ECX ; . DEC ECX ; ECX now contains the length MOVSX EAX, BYTE PTR [0040A680] ; Get byte at 40A680 IMUL ECX, EAX ; ECX = ECX * EAX SHL ECX, 0A ; Shift left 0A steps ADD ECX, 0002F8CC ; Add 2f8cc to the result MOV [0040A664], ECX And validated... CMP ECX, EDX ; Compare codes JZ 00402DA6 ; If equal, jump... When you have stepped to the comparison of the codes, you can check what your code REALLY should have been: :? ecx For me this gave: 000DC0CC 0000901324 This means that the right code for me is 901324. So press F5 or Ctrl+D to let it run, and try again, with the RIGHT code, but in decimal form. It will work! 4. MAKING A KEYMAKER FOR COMMAND LINE 95 ========================================= We look at the calculation of the code above, and translate it to C. We make this very simple description of how the code is calculated: code = ( (uppercase_first_char * length_of_string) << 0x0A) + 0x2f8cc; Note (1): One thing not to forget is that all chars are converted to uppercase when you enter them in the text box, so we have to do the same. Note (2): "<< 0x0A" means "multiply with 2^10" A whole program in C could look like this: #include#include int main() { unsigned long code; unsigned char buffer[0x1e]; printf("CommandLine95 Keymaker by ED!SON '96\n"); printf("Enter name: "); gets(buffer); strupr(buffer); code = ( ((unsigned long)buffer[0] * (unsigned long)strlen(buffer)) << 0x0A) + 0x2f8cc; printf("Your code is: %lu", code); return 0; } Enjoy! 4. HOW PUSH AND CALL AND THINGS REALLY WORK WHEN THE PROGRAM CALL A FUNCTION ============================================================================ We look at this piece of code from TaskLock again: PUSH 32 ; Save: Maximum size of string PUSH EAX ; Save: Address of text buffer PUSH 000003F4 ; Save: Identifier of control PUSH DWORD PTR [ESI+1C] ; Save: Handle of dialog box CALL [USER32!GetDlgItemTextA] ; Get the text If you call this from a C program, the call would look like this: GetDlgItemTextA(hwndDlg, 0x3F4, buffer, 0x32); ^ [ESI+1C] ^ EAX PUSH stores data on something called the stack. This results in that each PUSH put a new piece of data on top of the stack, and the function then checks what is lying on the stack and use it to do whatever it's supposed to. 5. ABOUT VISUAL BASIC PROGRAMS ============================== The Visual Basic .EXE files are not real, compiled EXEs. They just contain code to call VBRUNxxx.DLL, which reads data from the EXE to run the program. This is also why Visual Basic programs are so slow. And when the EXE files are not real, you can't disassemble them, you just find the call to the DLL and a lot of garbage, and when you debug, you end up in the DLL too. The solution is a decompiler. There is a decompiler for Visual Basic 2 & 3, made by someone called DoDi. It is shareware and available on the net. (See Appendix C) In Windows 95, there are Visual Basic version 4 32-bit apps, and for them there is no decompiler I know of, although I wish there was. Note: No real (or bright) programmer makes programs in Basic. A. MAKING SOFTICE LOAD SYMBOLS ============================== To check if SoftICE has loaded the symbols for GetWindowText, you enter SoftICE by pressing Ctrl+D and then write like this: :exp getwindowtext If you don't get all the GetWindowText functions listed, you need to edit \SIW95\WINICE.DAT by removing the comment chars (';') from some of the 'exp=' lines that follows this text: "Examples of export symbols that can be included for chicago" near the end of the file. You can remove comment chars from all of the lines, or to save memory, on just these files: kernel32.dll, user32.dll, gdi32.dll, which are the most important ones. When you're ready editing, you'll have to reboot the computer to make it work. B. Syntax for the functions ============================ It's always much easier to understand the function calls we talk about when you have the declarations, so here we go: int GetWindowText(int windowhandle, char *buffer, int maxlen); int GetDlgItemText(int dialoghandle, int controlid, char *buffer, int maxlen); int GetDlgItemInt(int dialoghandle, int controlid, int *flag, int type); For a more detailed description of the functions, check a Windows/Win32 programming reference. C. WHERE TO OBTAIN THE SOFTWARES ================================ CRACKING TOOLS SoftICE/Win 2.oo: http://www.geocities.com/SoHo/2680/cracking.html VB Decompiler: ftp://ftp.sn.no/user/balchen/vb/decompiler/ SAMPLE PROGRAMS TaskLock: http://users.aol.com/Sajernigan/sgllck30.zip CommandLine 95: ftp://ftp.winsite.com/pub/pc/win95/miscutil/cline95.zip D. CONTACTING ME ================ On IRC (EFNet): In #Ucf2000, #Cracking By e-mail: edison@ccnux.utm.my On my homepage: http://www.geocities.com/SoHo/2680/cracking.html ==============================================================================